home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 August (Alt) / CHIP 2005-08.1.iso / program / guvenlik / syslinux-3.07.exe / sample / printf.c < prev    next >
Encoding:
C/C++ Source or Header  |  2005-01-03  |  6.3 KB  |  308 lines

  1. /*
  2.  * Oh, it's a waste of space, but oh-so-yummy for debugging.  It's just
  3.  * initialization code anyway, so it doesn't take up space when we're
  4.  * actually running.  This version of printf() does not include 64-bit
  5.  * support.  "Live with it."
  6.  *
  7.  * Most of this code was shamelessly snarfed from the Linux kernel, then
  8.  * modified.
  9.  *
  10.  * FIX THIS: Replace printf() implementation with BSD/MIT-licensed one
  11.  * from klibc
  12.  */
  13.  
  14. #include <stdarg.h>
  15.  
  16. int puts(const char *);
  17.  
  18. static inline int
  19. isdigit(int ch)
  20. {
  21.   return (ch >= '0') && (ch <= '9');
  22. }
  23.  
  24. unsigned int skip_atou(const char **s);
  25. unsigned int atou(const char *s);
  26.  
  27. static int strnlen(const char *s, int maxlen)
  28. {
  29.   const char *es = s;
  30.   while ( *es && maxlen ) {
  31.     es++; maxlen--;
  32.   }
  33.  
  34.   return (es-s);
  35. }
  36.  
  37. #define ZEROPAD    1        /* pad with zero */
  38. #define SIGN    2        /* unsigned/signed long */
  39. #define PLUS    4        /* show plus */
  40. #define SPACE    8        /* space if plus */
  41. #define LEFT    16        /* left justified */
  42. #define SPECIAL    32        /* 0x */
  43. #define LARGE    64        /* use 'ABCDEF' instead of 'abcdef' */
  44.  
  45. #define do_div(n,base) ({ \
  46. int __res; \
  47. __res = ((unsigned long) n) % (unsigned) base; \
  48. n = ((unsigned long) n) / (unsigned) base; \
  49. __res; })
  50.  
  51. static char * number(char * str, long num, int base, int size, int precision
  52.     ,int type)
  53. {
  54.   char c,sign,tmp[66];
  55.   const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
  56.   int i;
  57.   
  58.   if (type & LARGE)
  59.     digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  60.   if (type & LEFT)
  61.     type &= ~ZEROPAD;
  62.   if (base < 2 || base > 36)
  63.     return 0;
  64.   c = (type & ZEROPAD) ? '0' : ' ';
  65.   sign = 0;
  66.   if (type & SIGN) {
  67.     if (num < 0) {
  68.       sign = '-';
  69.       num = -num;
  70.       size--;
  71.     } else if (type & PLUS) {
  72.       sign = '+';
  73.       size--;
  74.     } else if (type & SPACE) {
  75.       sign = ' ';
  76.       size--;
  77.     }
  78.   }
  79.   if (type & SPECIAL) {
  80.     if (base == 16)
  81.       size -= 2;
  82.     else if (base == 8)
  83.       size--;
  84.   }
  85.   i = 0;
  86.   if (num == 0)
  87.     tmp[i++]='0';
  88.   else while (num != 0)
  89.     tmp[i++] = digits[do_div(num,base)];
  90.   if (i > precision)
  91.     precision = i;
  92.   size -= precision;
  93.   if (!(type&(ZEROPAD+LEFT)))
  94.     while(size-->0)
  95.       *str++ = ' ';
  96.   if (sign)
  97.     *str++ = sign;
  98.   if (type & SPECIAL) {
  99.     if (base==8)
  100.       *str++ = '0';
  101.     else if (base==16) {
  102.       *str++ = '0';
  103.       *str++ = digits[33];
  104.     }
  105.   }
  106.   if (!(type & LEFT))
  107.     while (size-- > 0)
  108.       *str++ = c;
  109.   while (i < precision--)
  110.     *str++ = '0';
  111.   while (i-- > 0)
  112.     *str++ = tmp[i];
  113.   while (size-- > 0)
  114.     *str++ = ' ';
  115.   return str;
  116. }
  117.  
  118. /* Forward decl. needed for IP address printing stuff... */
  119. int sprintf(char * buf, const char *fmt, ...);
  120.  
  121. int vsprintf(char *buf, const char *fmt, va_list args)
  122. {
  123.   int len;
  124.   unsigned long num;
  125.   int i, base;
  126.   char * str;
  127.   const char *s;
  128.   
  129.   int flags;        /* flags to number() */
  130.   
  131.   int field_width;    /* width of output field */
  132.   int precision;        /* min. # of digits for integers; max
  133.                    number of chars for from string */
  134.   int qualifier;        /* 'h', 'l', or 'L' for integer fields */
  135.   
  136.   for (str=buf ; *fmt ; ++fmt) {
  137.     if (*fmt != '%') {
  138.       *str++ = *fmt;
  139.       continue;
  140.     }
  141.     
  142.     /* process flags */
  143.     flags = 0;
  144.   repeat:
  145.     ++fmt;        /* this also skips first '%' */
  146.     switch (*fmt) {
  147.     case '-': flags |= LEFT; goto repeat;
  148.     case '+': flags |= PLUS; goto repeat;
  149.     case ' ': flags |= SPACE; goto repeat;
  150.     case '#': flags |= SPECIAL; goto repeat;
  151.     case '0': flags |= ZEROPAD; goto repeat;
  152.     }
  153.     
  154.     /* get field width */
  155.     field_width = -1;
  156.     if (isdigit(*fmt))
  157.       field_width = skip_atou(&fmt);
  158.     else if (*fmt == '*') {
  159.       ++fmt;
  160.       /* it's the next argument */
  161.       field_width = va_arg(args, int);
  162.       if (field_width < 0) {
  163.     field_width = -field_width;
  164.     flags |= LEFT;
  165.       }
  166.     }
  167.     
  168.     /* get the precision */
  169.     precision = -1;
  170.     if (*fmt == '.') {
  171.       ++fmt;    
  172.       if (isdigit(*fmt))
  173.     precision = skip_atou(&fmt);
  174.       else if (*fmt == '*') {
  175.     ++fmt;
  176.     /* it's the next argument */
  177.     precision = va_arg(args, int);
  178.       }
  179.       if (precision < 0)
  180.     precision = 0;
  181.     }
  182.     
  183.     /* get the conversion qualifier */
  184.     qualifier = -1;
  185.     if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
  186.       qualifier = *fmt;
  187.       ++fmt;
  188.     }
  189.     
  190.     /* default base */
  191.     base = 10;
  192.     
  193.     switch (*fmt) {
  194.     case 'c':
  195.       if (!(flags & LEFT))
  196.     while (--field_width > 0)
  197.       *str++ = ' ';
  198.       *str++ = (unsigned char) va_arg(args, int);
  199.       while (--field_width > 0)
  200.     *str++ = ' ';
  201.       continue;
  202.       
  203.     case 's':
  204.       s = va_arg(args, char *);
  205.       len = strnlen(s, precision);
  206.       
  207.       if (!(flags & LEFT))
  208.     while (len < field_width--)
  209.       *str++ = ' ';
  210.       for (i = 0; i < len; ++i)
  211.     *str++ = *s++;
  212.       while (len < field_width--)
  213.     *str++ = ' ';
  214.       continue;
  215.       
  216.     case 'p':
  217.       if (field_width == -1) {
  218.     field_width = 2*sizeof(void *);
  219.     flags |= ZEROPAD;
  220.       }
  221.       str = number(str,
  222.            (unsigned long) va_arg(args, void *), 16,
  223.            field_width, precision, flags);
  224.       continue;
  225.       
  226.       
  227.     case 'n':
  228.       if (qualifier == 'l') {
  229.     long * ip = va_arg(args, long *);
  230.     *ip = (str - buf);
  231.       } else {
  232.     int * ip = va_arg(args, int *);
  233.     *ip = (str - buf);
  234.       }
  235.       continue;
  236.       
  237.     case '%':
  238.       *str++ = '%';
  239.       continue;
  240.       
  241.       /* integer number formats - set up the flags and "break" */
  242.     case 'o':
  243.       base = 8;
  244.       break;
  245.       
  246.     case 'X':
  247.       flags |= LARGE;
  248.     case 'x':
  249.       base = 16;
  250.       break;
  251.       
  252.     case 'd':
  253.     case 'i':
  254.       flags |= SIGN;
  255.     case 'u':
  256.       break;
  257.       
  258.     default:
  259.       *str++ = '%';
  260.       if (*fmt)
  261.     *str++ = *fmt;
  262.       else
  263.     --fmt;
  264.       continue;
  265.     }
  266.     if (qualifier == 'l')
  267.       num = va_arg(args, unsigned long);
  268.     else if (qualifier == 'h') {
  269.       num = (unsigned short) va_arg(args, int);
  270.       if (flags & SIGN)
  271.     num = (short) num;
  272.     } else if (flags & SIGN)
  273.       num = va_arg(args, int);
  274.     else
  275.       num = va_arg(args, unsigned int);
  276.     str = number(str, num, base, field_width, precision, flags);
  277.   }
  278.   *str = '\0';
  279.   return str-buf;
  280. }
  281.  
  282. int sprintf(char * buf, const char *fmt, ...)
  283. {
  284.   va_list args;
  285.   int i;
  286.   
  287.   va_start(args, fmt);
  288.   i=vsprintf(buf,fmt,args);
  289.   va_end(args);
  290.   return i;
  291. }
  292.  
  293. int printf(const char *fmt, ...)
  294. {
  295.   char printf_buf[1024];
  296.   va_list args;
  297.   int printed;
  298.  
  299.   va_start(args, fmt);
  300.   printed = vsprintf(printf_buf, fmt, args);
  301.   va_end(args);
  302.  
  303.   puts(printf_buf);
  304.  
  305.   return printed;
  306. }
  307.  
  308.